using System;
using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using Firestarter.DB.Schema.BO;
using Firestarter.DB.Schema.Logic;
using Firestarter.DB.Schema.Test.BO;
using Firestarter.DB.Schema.Test.BO.TestUtils;
using Firestarter.DB.Schema.Test.Logic.DBMerge;
using Firestarter.Test.Base.BusinessObjectMerger;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using Habanero.BO.Loaders;
using Habanero.Testability;
using NUnit.Framework;

namespace Firestarter.DB.Schema.Test.Logic
{
    [TestFixture]
    public class TestMergeDBForeignKey
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            ClassDef.ClassDefs.Clear();
            string xmlClassDefs = BOBroker.GetClassDefsXml();
            ClassDef.ClassDefs.Add(new XmlClassDefsLoader(xmlClassDefs, new DtdLoader()).LoadClassDefs());
            BORegistry.DataAccessor = new DataAccessorInMemory();

            MergeableBORegistry.Instance.Register<DBForeignKey, DBMergeDBForeignKey>();
            MergeableBORegistry.Instance.Register<DBForeignKeyColumn, DBMergeDBForeignKeyColumn>();
        }

        [SetUp]
        public virtual void SetupTest()
        {
        }

        [TestCase("ForeignKeyName", true)]
        [TestCase("ForeignKeyID", false)]
        [TestCase("ParentTableID", false)]
        [TestCase("Approved", false)]
        [TestCase("PendingChangeType", false)]
        [TestCase("RelatedTableID", false)]
        public void Test_MustMergeProp_ShouldBeSetForProp(string propName, bool expectedMustMergeProp)
        {
            //---------------Set up test pack-------------------
            DBMergeBO<DBForeignKey> merger = (DBMergeBO<DBForeignKey>)GetFKMerger();
            var dbForeignKey = new DBForeignKey();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            var boProp = dbForeignKey.Props[propName];
            var returnedMustMergeProp = merger.MustMergeProperty(boProp);
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedMustMergeProp, returnedMustMergeProp, "Prop '" + propName + "' should be MustMerge = '" + expectedMustMergeProp +"'");
        }

        [TestCase("ForeignKeyColumns", true)]
        [TestCase("MappedDMRelationship", false)]
        [TestCase("ParentTable", false)]
        [TestCase("RelatedTable", false)]
        public void Test_MustMergeRelationship_ShouleBeSetForRelationships(string relationshipName, bool expectedMustMergeRel)
        {
            //---------------Set up test pack-------------------
            DBMergeBO<DBForeignKey> merger = (DBMergeBO<DBForeignKey>)GetFKMerger();
            var dbForeignKey = new DBForeignKey();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------

            var relationship = dbForeignKey.Relationships[relationshipName];
            var returnedMustMergeProp = merger.MustMergeRelationship(relationship);
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedMustMergeRel, returnedMustMergeProp, "Relationship '" + relationship.RelationshipName + "' should be MustMerge = '" + expectedMustMergeRel + "'");
        }

        [Test]
        public void Test_MatchBusinessObject_WhenFKNameEqual_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            DBForeignKey fromFK = new DBForeignKey
                                      {
                                          ForeignKeyName = RandomValueGen.GetRandomString()
                                      };
            DBForeignKey toFK = new DBForeignKey {ForeignKeyName = fromFK.ForeignKeyName};

            DBMergeBO<DBForeignKey> fkMerger = (DBMergeBO<DBForeignKey>)GetFKMerger();
            //---------------Assert Precondition----------------
            Assert.AreEqual(fromFK.ForeignKeyName, toFK.ForeignKeyName);
            Assert.AreEqual(fromFK.ToString(), toFK.ToString());
            //---------------Execute Test ----------------------
            var function = fkMerger.MatchBusinessObject(fromFK);
            var matchRelationship = function(toFK);
            //---------------Test Result -----------------------
            Assert.IsTrue(matchRelationship);
        }

        [Test]
        public void Test_MatchBusinessObject_WhenFKNameNotEqual_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            DBForeignKey fromFK = new DBForeignKey
                                      {
                                          ForeignKeyName = RandomValueGen.GetRandomString()
                                      };
            DBForeignKey toFK = new DBForeignKey
                                    {
                                        ForeignKeyName = RandomValueGen.GetRandomString()
                                    };

            DBMergeBO<DBForeignKey> fkMerger = (DBMergeBO<DBForeignKey>)GetFKMerger();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(fromFK.ForeignKeyName, toFK.ForeignKeyName);
            Assert.AreNotEqual(fromFK.ToString(), toFK.ToString());
            //---------------Execute Test ----------------------
            var function = fkMerger.MatchBusinessObject(fromFK);
            var matchRelationship = function(toFK);
            //---------------Test Result -----------------------
            Assert.IsFalse(matchRelationship);
        }

        [Test]
        public void Test_MatchBO_WhenTableNameNotEqual_BUtKeyNameEqual_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------

            DBForeignKey fromFK = TestUtilsDBForeignKey.GetTestFactory()
                .CreateValidBusinessObject();
            DBForeignKey toFK = TestUtilsDBForeignKey.GetTestFactory()
                .WithValue(foreignKey => foreignKey.ForeignKeyName, fromFK.ForeignKeyName)
                .CreateValidBusinessObject();

            var fkMerger = (DBMergeBO<DBForeignKey>)GetFKMerger();
            //---------------Assert Precondition----------------
            Assert.AreEqual(fromFK.ForeignKeyName, toFK.ForeignKeyName);
            Assert.AreNotEqual(fromFK.ParentTable, toFK.ParentTable);
            Assert.AreNotEqual(fromFK.ParentTable.TableName, toFK.ParentTable.TableName);
            Assert.AreEqual(fromFK.ToString(), toFK.ToString());
            //---------------Execute Test ----------------------
            var function = fkMerger.MatchBusinessObject(fromFK);
            var matchRelationship = function(toFK);
            //---------------Test Result -----------------------
            Assert.IsTrue(matchRelationship);
        }

        [Test]
        public void Test_MergeFK_WithAddedFKColumn_ShouldCreateMergedFKColumn_AndCreateColumns()
        {
            //---------------Set up test pack-------------------
            var fromFK = CreateFK();
            var toFK = GetFKMerger().MergeBOFrom(fromFK, null);
            toFK.ParentTable = new DBTable();
            toFK.RelatedTable = new DBTable();
            var fromFKColumn = CreateFKColumn(fromFK, GetRandomString(), GetRandomString());

            //---------------Assert Precondition---------------
            Assert.AreEqual(1, fromFK.ForeignKeyColumns.Count);
            Assert.IsNotNull(fromFKColumn.ParentColumn);
            Assert.IsNotNull(fromFKColumn.RelatedColumn);
            Assert.IsNotNull(fromFK.ParentTable);
            Assert.IsNotNull(fromFK.RelatedTable);

            Assert.AreEqual(0, toFK.ForeignKeyColumns.Count);
            Assert.IsNotNull(toFK.ParentTable);
            Assert.IsNotNull(toFK.RelatedTable);
            //---------------Execute Test ----------------------
            DBMergeBO<DBForeignKey> merger = (DBMergeBO<DBForeignKey>)GetFKMerger();
            merger.MergeBOFrom(fromFK, toFK);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, toFK.ForeignKeyColumns.Count);
            var createdFKColumn = toFK.ForeignKeyColumns[0];

            Assert.AreEqual(fromFKColumn.ParentColumnName, createdFKColumn.ParentColumnName);
            Assert.AreEqual(fromFKColumn.RelatedColumnName, createdFKColumn.RelatedColumnName);
        }

        [Test]
        public void Test_MergeFK_WithAddedFKColumn_ShouldAddCreatedColumnsToParentAndRelatedTables()
        {
            //---------------Set up test pack-------------------
            var fromFK = CreateFK();
            var toFK = GetFKMerger().MergeBOFrom(fromFK, null);
            var toDatabase = new DBDatabase();
            SetRelatedTable(fromFK, toFK, toDatabase);

            var fromFKColumn = CreateFKColumn(fromFK, GetRandomString(), GetRandomString());

            //---------------Assert Precondition---------------
            Assert.AreEqual(1, fromFK.ForeignKeyColumns.Count);
            Assert.IsNotNull(fromFKColumn.ParentColumn);
            Assert.IsNotNull(fromFKColumn.RelatedColumn);
            Assert.IsNotNull(fromFK.ParentTable);
            Assert.IsNotNull(fromFK.RelatedTable);

            Assert.AreEqual(0, toFK.ForeignKeyColumns.Count);
            Assert.IsNotNull(toFK.ParentTable);
            Assert.IsNotNull(toFK.RelatedTable);

            Assert.AreEqual(0, toFK.ParentTable.Columns.Count);
            Assert.AreEqual(0, toFK.RelatedTable.Columns.Count);
            //---------------Execute Test ----------------------
            DBMergeBO<DBForeignKey> merger = (DBMergeBO<DBForeignKey>)GetFKMerger();
            merger.MergeBOFrom(fromFK, toFK);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, toFK.ForeignKeyColumns.Count);
            var createdFKColumn = toFK.ForeignKeyColumns[0];

            Assert.AreEqual(fromFKColumn.ParentColumnName, createdFKColumn.ParentColumnName);
            Assert.AreEqual(fromFKColumn.RelatedColumnName, createdFKColumn.RelatedColumnName);

            Assert.IsTrue(toFK.ParentTable.Columns.Contains(createdFKColumn.ParentColumn));
            Assert.IsTrue(toFK.RelatedTable.Columns.Contains(createdFKColumn.RelatedColumn));
            Assert.AreEqual(ChangeType.Add, createdFKColumn.ParentColumn.PendingChangeType);
            Assert.AreEqual(ChangeType.Add, createdFKColumn.RelatedColumn.PendingChangeType);
        }

        private void SetRelatedTable(DBForeignKey fromFK, DBForeignKey toFK, DBDatabase toDatabase)
        {
            toFK.ParentTable = new DBTable { Database = toDatabase };
            var expectedToRelatedTable = toDatabase.Tables.CreateBusinessObject();
            expectedToRelatedTable.TableName = fromFK.RelatedTableName;
            toFK.RelatedTable = expectedToRelatedTable;
        }

        [Test]
        public void Test_MergeFK_WhenRelatedTableNotInDB_ShouldCreateRelatedTable()
        {
            //---------------Set up test pack-------------------
            var fromFK = CreateFKWithDatabase();
            var toFK = GetFKMerger().MergeBOFrom(fromFK, null);
            toFK.ParentTable = new DBTable {Database = new DBDatabase()};

            //---------------Assert Precondition---------------
            Assert.IsNotNull(fromFK.ParentTable);
            Assert.IsNotNull(fromFK.RelatedTable);
            Assert.IsNotNull(fromFK.ParentTable.Database);
            Assert.IsNotNull(fromFK.RelatedTable.Database);

            Assert.IsNotNull(toFK.ParentTable);
            Assert.IsNotNull(toFK.ParentTable.Database);
            Assert.IsNull(toFK.RelatedTable);
            //---------------Execute Test ----------------------
            GetFKMerger().MergeBOFrom(fromFK, toFK);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toFK.ParentTable);
            Assert.IsNotNull(toFK.ParentTable.Database);
            Assert.IsNotNull(toFK.RelatedTable, "Should have linked RelatedTable");
            Assert.IsNotNull(toFK.RelatedTable.Database);
            Assert.AreSame(toFK.ParentTable.Database, toFK.RelatedTable.Database);
            Assert.AreEqual(ChangeType.Add, toFK.RelatedTable.PendingChangeType);
        }
        [Test]
        public void Test_MergeFK_WhenRelatedTableNotInDB_ShouldCreateRelatedTable_AndCreateRelatedPropOnTable()
        {
            //---------------Set up test pack-------------------
            var fromFK = CreateFKWithDatabase();
            var toFK = GetFKMerger().MergeBOFrom(fromFK, null);
            toFK.ParentTable = new DBTable {Database = new DBDatabase()};
            CreateFKColumn(fromFK, GetRandomString(), GetRandomString());

            //---------------Assert Precondition---------------
            Assert.IsNotNull(fromFK.ParentTable);
            Assert.IsNotNull(fromFK.RelatedTable);
            Assert.IsNotNull(fromFK.ParentTable.Database);
            Assert.IsNotNull(fromFK.RelatedTable.Database);
            Assert.AreEqual(1, fromFK.ForeignKeyColumns.Count);
            var dbForeignKeyColumn = fromFK.ForeignKeyColumns[0];
            Assert.IsNotNull(dbForeignKeyColumn.ParentColumn);
            Assert.IsNotNull(dbForeignKeyColumn.RelatedColumn);

            Assert.IsNotNull(toFK.ParentTable);
            Assert.IsNotNull(toFK.ParentTable.Database);
            Assert.IsNull(toFK.RelatedTable);
            //---------------Execute Test ----------------------
            GetFKMerger().MergeBOFrom(fromFK, toFK);
            //---------------Test Result -----------------------
            var relatedTable = toFK.RelatedTable;
            Assert.IsNotNull(relatedTable, "Should have linked RelatedTable");
            Assert.AreEqual(1, relatedTable.Columns.Count, "Should have added relatedColumn to related table");
            Assert.AreEqual(1, toFK.ForeignKeyColumns.Count);
            Assert.IsNotNull(toFK.ForeignKeyColumns[0].ParentColumn);
            Assert.IsNotNull(toFK.ForeignKeyColumns[0].RelatedColumn);
        }

        [Test]
        public void Test_MergeFK_WhenRelatedTableInDB_ShouldLinkToRelatedTable()
        {
            //---------------Set up test pack-------------------
            var fromFK = CreateFKWithDatabase();
            var toFK = GetFKMerger().MergeBOFrom(fromFK, null);

            var toDatabase = new DBDatabase();
            toFK.ParentTable = new DBTable { Database = toDatabase };
            var expectedToRelatedTable = toDatabase.Tables.CreateBusinessObject();
            expectedToRelatedTable.TableName = fromFK.RelatedTableName;
            //---------------Assert Precondition---------------
            Assert.IsNotNull(fromFK.ParentTable);
            Assert.IsNotNull(fromFK.RelatedTable);
            Assert.IsNotNull(fromFK.ParentTable.Database);
            Assert.IsNotNull(fromFK.RelatedTable.Database);

            Assert.AreEqual(0, toFK.ForeignKeyColumns.Count);

            Assert.IsNotNull(toFK.ParentTable);
            var returnedRelatedTable = toDatabase.Tables.Find(table => table.TableName == fromFK.RelatedTableName);
            Assert.AreSame(expectedToRelatedTable, returnedRelatedTable);

            Assert.IsNull(toFK.RelatedTable, "The to FK should not already be linked to this related table");
            //---------------Execute Test ----------------------
            GetFKMerger().MergeBOFrom(fromFK, toFK);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toFK.ParentTable.Database);
            Assert.IsNotNull(toFK.RelatedTable, "Should have linked RelatedTable");
            Assert.AreSame(toFK.ParentTable.Database, toFK.RelatedTable.Database);
            Assert.AreSame(expectedToRelatedTable, toFK.RelatedTable);
        }

        private static string GetRandomString()
        {
            return RandomValueGen.GetRandomString();
        }

        private static DBForeignKey CreateFKWithDatabase()
        {
            DBDatabase database = TestUtilsDBDatabase.GetTestFactory()
                .CreateValidBusinessObject();
            return CreateFK(database);
        }

        private static DBForeignKey CreateFK(DBDatabase database)
        {
            var parentTable = TestUtilsDBTable.GetTestFactory()
                 .WithValue(table => table.Database, database)
                 .CreateValidBusinessObject();
            var relatedTable = TestUtilsDBTable.GetTestFactory()
                .WithValue(table => table.Database, database)
                .CreateValidBusinessObject();
            return CreateFK(parentTable, relatedTable);
        }

        private static DBForeignKey CreateFK()
        {
            DBDatabase database = null;
            return CreateFK(database);
        }

        private static IMergeBO<DBForeignKey> GetFKMerger()
        {
            return MergeableBORegistry.Instance.Resolve<DBForeignKey>();
        }

        private static DBForeignKey CreateFK(DBTable parentTable)
        {
            var relatedTable = TestUtilsDBTable.GetTestFactory()
                .WithValue(table => table.Database, null)
                .CreateValidBusinessObject();
            return CreateFK(parentTable, relatedTable);
        }

        private static DBForeignKey CreateFK(DBTable parentTable, DBTable relatedTable)
        {
            return TestUtilsDBForeignKey.GetTestFactory()
                .WithValue(relationship => relationship.ParentTable, parentTable)
                .WithValue(relationship => relationship.RelatedTable, relatedTable)
                .CreateValidBusinessObject();
        }

        private static DBForeignKeyColumn CreateFKColumn(DBForeignKey fK, DBColumn parentColumn)
        {
            return TestUtilsDBForeignKeyColumn.GetTestFactory()
                .WithValue(relProp => relProp.ForeignKey, fK)
                .WithValue(relProp => relProp.ParentColumn, parentColumn)
                .WithValue(property => property.RelatedColumn, null)
                .CreateValidBusinessObject();
        }

        private static DBForeignKeyColumn CreateFKColumn(DBForeignKey fK, string parentColumnName, string relColumnName)
        {

            var relatedColumn = TestUtilsDBColumn.GetTestFactory()
                .WithValue(column => column.ColumnName, relColumnName)
                .WithValue(column => column.Table, fK.RelatedTable)
                .CreateValidBusinessObject();

            var parentColumn = TestUtilsDBColumn.GetTestFactory()
                .WithValue(column => column.ColumnName, parentColumnName)
                .WithValue(column => column.Table, fK.ParentTable)
                .CreateValidBusinessObject();

            return CreateFKColumn(fK, relatedColumn, parentColumn);
        }

        private static DBForeignKeyColumn CreateFKColumn(DBForeignKey fK, DBColumn relatedColumn, DBColumn parentColumn)
        {
            return TestUtilsDBForeignKeyColumn.GetTestFactory()
                .WithValue(property => property.ForeignKey, fK)
                .WithValue(property => property.RelatedColumn, relatedColumn)
                .WithValue(property => property.ParentColumn, parentColumn)
                .CreateValidBusinessObject();
        }

        private static DBForeignKeyColumn CreateFKColumnWithFK(string fkName, string parentColumnName)
        {
            var foreignKey = TestUtilsDBForeignKey.GetTestFactory()
                .WithValue(relationship => relationship.ForeignKeyName, fkName)
                .CreateValidBusinessObject();

            var dbColumn = TestUtilsDBColumn.GetTestFactory()
                .WithValue(column => column.ColumnName, parentColumnName)
                .WithValue(column => column.Table, null)
                .CreateValidBusinessObject();
            return CreateFKColumn(foreignKey, dbColumn);
        }

        /*
        


                [Test]
                public void Test_MergeRelationship_WithAddedRelationship_ShouldCreateMergedRelationship()
                {
                    //---------------Set up test pack-------------------
                    DMProperty ownerProp;
                    DMClass ownerFromClass = GetClassWithOneProp(out ownerProp);
                    DBMergeBO<DMClass> tempMerger = new DBMergeBO<DMClass>();
                    //Create a second class that is an exact duplicate of the first class without
                    // the relationships.
                    DMClass ownerToClass = tempMerger.MergeBOFrom(ownerFromClass, null);
                    //Add the relationships to the first class.
                    DBForeignKey fromRelationship = CreateRelationship(ownerFromClass);
                    DBForeignKeyColumn ownerRelProp = CreateFKColumn(fromRelationship, ownerProp);

                    SetRelatedClass(fromRelationship, ownerRelProp);

                    //---------------Assert Precondition----------------
                    Assert.AreEqual(1, ownerFromClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, fromRelationship.RelationshipProperties.Count);

                    Assert.AreEqual(0, ownerToClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, ownerToClass.Properties.Count);
                    //---------------Execute Test ----------------------
                    DBMergeBO<DMClass> merger = new DBMergeBO<DMClass>();
                    var mergedOwnerToClass = merger.MergeBOFrom(ownerFromClass, ownerToClass);
                    //---------------Test Result -----------------------
                    Assert.AreEqual(1, mergedOwnerToClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, mergedOwnerToClass.Properties.Count);

                    var toRelationship = mergedOwnerToClass.RelationshipsDM[0];
                    Assert.AreEqual(toRelationship.RelationshipName, fromRelationship.RelationshipName);
                    Assert.IsNull(toRelationship.ReverseRelationship, "The reverse relationship will be fixed in the Post Load Processor for now should be null");
                }

                [Test]
                public void Test_MergeRelationship_WithAddedRelationship_ShouldCreateRelWithSpecialPropsSet()
                {
                    //---------------Set up test pack-------------------
                    DMProperty ownerProp;
                    DMClass ownerFromClass = GetClassWithOneProp(out ownerProp);
                    DBMergeBO<DMClass> tempMerger = new DBMergeBO<DMClass>();
                    //Create a second class that is an exact duplicate of the first class without
                    // the relationships.
                    DMClass ownerToClass = tempMerger.MergeBOFrom(ownerFromClass, null);
                    //Add the relationships to the first class.
                    DBForeignKey fromRelationship = CreateRelationship(ownerFromClass);
                    DBForeignKeyColumn ownerRelProp = CreateFKColumn(fromRelationship, ownerProp);

                    SetRelatedClass(fromRelationship, ownerRelProp);
                    //---------------Assert Precondition----------------
                    Assert.AreEqual(1, ownerFromClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, fromRelationship.RelationshipProperties.Count);
                    Assert.IsNotNull(fromRelationship.ReverseRelationship);
                    Assert.IsNotNull(fromRelationship.ReverseRelationshipName);
                    Assert.IsNotNull(fromRelationship.RelatedClassName);
                    Assert.IsNotNull(fromRelationship.RelatedAssemblyName);

                    Assert.AreEqual(0, ownerToClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, ownerToClass.Properties.Count);

                    //---------------Execute Test ----------------------
                    var mergedOwnerToClass = new DBMergeBO<DMClass>().MergeBOFrom(ownerFromClass, ownerToClass);
                    //---------------Test Result -----------------------
                    Assert.AreEqual(1, mergedOwnerToClass.RelationshipsDM.Count);
                    var toRelationship = mergedOwnerToClass.RelationshipsDM[0];

                    Assert.IsNull(toRelationship.ReverseRelationship, "The reverse relationship will be fixed in the Post Load Processor for now should be null");
                    Assert.AreEqual(fromRelationship.ReverseRelationshipName, toRelationship.ReverseRelationshipName);
                    Assert.AreEqual(fromRelationship.RelatedClassName, toRelationship.RelatedClassName);
                    Assert.AreEqual(fromRelationship.RelatedAssemblyName, toRelationship.RelatedAssemblyName);
                }


                [Test]
                public void Test_MergeRelationship_WithAddedRelationship_ShouldCreateRelPropWithSpecialPropsSet()
                {
                    //---------------Set up test pack-------------------
                    DMProperty ownerProp;
                    DMClass ownerFromClass = GetClassWithOneProp(out ownerProp);
                    DBMergeBO<DMClass> tempMerger = new DBMergeBO<DMClass>();
                    //Create a second class that is an exact duplicate of the first class without
                    // the relationships.
                    DMClass ownerToClass = tempMerger.MergeBOFrom(ownerFromClass, null);
                    //Add the relationships to the first class.
                    DBForeignKey fromRelationship = CreateRelationship(ownerFromClass);
                    DBForeignKeyColumn ownerRelProp = CreateFKColumn(fromRelationship, ownerProp);

                    SetRelatedClass(fromRelationship, ownerRelProp);
                    //---------------Assert Precondition----------------
                    Assert.AreEqual(1, ownerFromClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, fromRelationship.RelationshipProperties.Count);
                    Assert.IsNotNull(ownerRelProp.ReverseRelationshipProperty);
                    Assert.IsNotNull(ownerRelProp.RelatedPropertyName);

                    Assert.AreEqual(0, ownerToClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, ownerToClass.Properties.Count);

                    //---------------Execute Test ----------------------
                    var mergedOwnerToClass = new DBMergeBO<DMClass>().MergeBOFrom(ownerFromClass, ownerToClass);
                    //---------------Test Result -----------------------
                    Assert.AreEqual(1, mergedOwnerToClass.RelationshipsDM.Count);
                    var toRelationship = mergedOwnerToClass.RelationshipsDM[0];


                    Assert.AreEqual(1, toRelationship.RelationshipProperties.Count);
                    var toFKColumn = toRelationship.RelationshipProperties[0];
                    Assert.IsNull(toFKColumn.RelatedProperty);
                    Assert.IsNull(toFKColumn.ReverseRelationshipProperty);
                    Assert.AreEqual(ownerRelProp.RelatedPropertyName, toFKColumn.RelatedPropertyName);
                }


                [Test]
                public void Test_MergeAssembly_WithDMClassAddedRelationship_ShouldCreateRelPropWithSpecialPropsSet()
                {
                    //---------------Set up test pack-------------------
                    DMProperty ownerProp;
                    DMClass ownerFromClass = GetClassWithOneProp(out ownerProp);
                    ownerFromClass.Assembly = GetValidAssembly(null);
                    DBMergeBO<DMClass> tempMerger = new DBMergeBO<DMClass>();
                    //Create a second class that is an exact duplicate of the first class without
                    // the relationships.
                    DMClass ownerToClass = tempMerger.MergeBOFrom(ownerFromClass, null);
                    ownerToClass.Assembly = GetValidAssembly(null);
                    //Add the relationships to the first class.
                    DBForeignKey fromRelationship = CreateRelationship(ownerFromClass);
                    DBForeignKeyColumn ownerRelProp = CreateFKColumn(fromRelationship, ownerProp);

                    DMProperty relatedProp;
                    DMClass relatedFromClass = GetClassWithOneProp(out relatedProp);
                    relatedFromClass.Assembly = ownerFromClass.Assembly;
                    SetRelatedClass(fromRelationship, relatedFromClass, ownerRelProp, relatedProp);

                    //---------------Assert Precondition----------------
                    Assert.AreEqual(1, ownerFromClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, fromRelationship.RelationshipProperties.Count);
                    Assert.IsNotNull(ownerRelProp.ReverseRelationshipProperty);
                    Assert.IsNotNull(ownerRelProp.RelatedPropertyName);

                    Assert.AreEqual(0, ownerToClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, ownerToClass.Properties.Count);

                    //---------------Execute Test ----------------------
                    new DBMergeBO<DMAssembly>().MergeBOFrom(ownerFromClass.Assembly, ownerToClass.Assembly);
                    //---------------Test Result -----------------------

                    Assert.AreEqual(1, ownerToClass.RelationshipsDM.Count);
                    var toRelationship = ownerToClass.RelationshipsDM[0];

                    Assert.IsNull(toRelationship.ReverseRelationship, "The reverse relationship will be fixed in the Post Load Processor for now should be null");
                    Assert.AreEqual(fromRelationship.ReverseRelationshipName, toRelationship.ReverseRelationshipName);
                    Assert.AreEqual(fromRelationship.RelatedClassName, toRelationship.RelatedClassName);
                    Assert.AreEqual(fromRelationship.RelatedAssemblyName, toRelationship.RelatedAssemblyName);

                    Assert.AreEqual(1, toRelationship.RelationshipProperties.Count);
                    var toFKColumn = toRelationship.RelationshipProperties[0];
                    Assert.IsNull(toFKColumn.RelatedProperty);
                    Assert.IsNull(toFKColumn.ReverseRelationshipProperty);
                    Assert.AreEqual(ownerRelProp.RelatedPropertyName, toFKColumn.RelatedPropertyName);
                }

                [Test]
                public void Test_Accept_MergeSolution_WithDMClassAddedRelationship_ShouldCreateRelPropWithSpecialPropsSet()
                {
                    //---------------Set up test pack-------------------
                    DMProperty ownerProp;
                    DMClass ownerFromClass = GetClassWithOneProp(out ownerProp);
                    SolutionCreator creator = new SolutionCreator();
                    var fromSolution = creator.CreateSolution();
                    var toSolution = new DBMergeBO<DMSolution>().MergeBOFrom(fromSolution, null);
                    ownerFromClass.Assembly = fromSolution.DefaultAssembly;

                    DBMergeBO<DMClass> tempMerger = new DBMergeBO<DMClass>();
                    //Create a second class that is an exact duplicate of the first class without
                    // the relationships.
                    DMClass ownerToClass = tempMerger.MergeBOFrom(ownerFromClass, null);

                    ownerToClass.Assembly = toSolution.Assemblies[0];


                    //Add the relationships to the first class.
                    DBForeignKey fromRelationship = CreateRelationship(ownerFromClass);
                    DBForeignKeyColumn ownerRelProp = CreateFKColumn(fromRelationship, ownerProp);

                    DMProperty relatedProp;
                    DMClass relatedFromClass = GetClassWithOneProp(out relatedProp);
                    relatedFromClass.Assembly = ownerFromClass.Assembly;
                    SetRelatedClass(fromRelationship, relatedFromClass, ownerRelProp, relatedProp);

                    //---------------Assert Precondition----------------
                    Assert.AreEqual(1, ownerFromClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, fromRelationship.RelationshipProperties.Count);
                    Assert.IsNotNull(ownerRelProp.ReverseRelationshipProperty);
                    Assert.IsNotNull(ownerRelProp.RelatedPropertyName);
                    Assert.AreEqual(2, fromSolution.Assemblies[0].Classes.Count, "Should have owner and related class for the relationship");

                    Assert.AreEqual(0, ownerToClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, ownerToClass.Properties.Count);
                    Assert.IsNotNull(ownerToClass.Assembly);
                    Assert.AreSame(toSolution, ownerToClass.Solution);
                    Assert.AreEqual(1, toSolution.Assemblies[0].Classes.Count, "Should have owner and related class for the relationship");
                    //---------------Execute Test ----------------------
                    var mergedSolution = new DBMergeBO<DMSolution>().MergeBOFrom(fromSolution, toSolution);
                    //---------------Test Result -----------------------
                    Assert.AreSame(mergedSolution, toSolution);
                    Assert.AreSame(mergedSolution, ownerToClass.Solution);
                    Assert.AreEqual(1, mergedSolution.Assemblies.Count);

                    var mergedAssembly = mergedSolution.Assemblies[0];
                    Assert.AreEqual(2, mergedAssembly.Classes.Count, "Created New Related Class");
                    Assert.AreEqual(1, ownerToClass.RelationshipsDM.Count);
                    var toRelationship = ownerToClass.RelationshipsDM[0];
                    Assert.IsNull(toRelationship.ReverseRelationship, "The reverse relationship will be fixed in the Post Load Processor for now should be null");
                    Assert.AreEqual(fromRelationship.ReverseRelationshipName, toRelationship.ReverseRelationshipName);
                    Assert.AreEqual(fromRelationship.RelatedClassName, toRelationship.RelatedClassName);
                    Assert.AreEqual(fromRelationship.RelatedAssemblyName, toRelationship.RelatedAssemblyName);

                    Assert.AreEqual(1, toRelationship.RelationshipProperties.Count);
                    var toFKColumn = toRelationship.RelationshipProperties[0];
                    Assert.IsNull(toFKColumn.RelatedProperty);
                    Assert.IsNotNull(toFKColumn.OwnerPropertyName);
                    Assert.IsNull(toFKColumn.ReverseRelationshipProperty);
                    Assert.AreEqual(ownerRelProp.RelatedPropertyName, toFKColumn.RelatedPropertyName);

                    //Check Reverse Relationship created on RelatedClass
                    var relatedToClass = mergedAssembly.Classes.Find(@class => @class != ownerToClass);
                    Assert.AreEqual(1, relatedToClass.RelationshipsDM.Count);
                    var reverseToRelationship = relatedToClass.RelationshipsDM[0];
                    Assert.AreEqual(ownerToClass.ClassNameBO, reverseToRelationship.RelatedClassName);
                    Assert.IsNull(reverseToRelationship.ReverseRelationship);
                    Assert.AreEqual(1, reverseToRelationship.RelationshipProperties.Count);
                    var reverseToRelProp = reverseToRelationship.RelationshipProperties[0];
                    Assert.IsNull(reverseToRelProp.RelatedProperty);
                    Assert.IsNull(reverseToRelProp.ReverseRelationshipProperty);
                    Assert.AreEqual(ownerProp.PropertyName, reverseToRelProp.RelatedPropertyName);
                }

                [Test]
                public void Test_Accept_PostLoadProcessMergedSolution_ShouldFixReverseRelationshipAndReverseRelProps()
                {
                    //---------------Set up test pack-------------------
                    DMProperty ownerProp;
                    DMClass ownerFromClass = GetClassWithOneProp(out ownerProp);
                    SolutionCreator creator = new SolutionCreator();
                    var fromSolution = creator.CreateSolution();
                    var toSolution = new DBMergeBO<DMSolution>().MergeBOFrom(fromSolution, null);
                    ownerFromClass.Assembly = fromSolution.DefaultAssembly;

                    DBMergeBO<DMClass> tempMerger = new DBMergeBO<DMClass>();
                    //Create a second class that is an exact duplicate of the first class without
                    // the relationships.
                    DMClass ownerToClass = tempMerger.MergeBOFrom(ownerFromClass, null);

                    ownerToClass.Assembly = toSolution.Assemblies[0];


                    //Add the relationships to the first class.
                    DBForeignKey fromRelationship = CreateRelationship(ownerFromClass);
                    DBForeignKeyColumn ownerRelProp = CreateFKColumn(fromRelationship, ownerProp);

                    DMProperty relatedProp;
                    DMClass relatedFromClass = GetClassWithOneProp(out relatedProp);
                    relatedFromClass.Assembly = ownerFromClass.Assembly;
                    SetRelatedClass(fromRelationship, relatedFromClass, ownerRelProp, relatedProp);

                    //---------------Assert Precondition----------------
                    Assert.AreEqual(1, ownerFromClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, fromRelationship.RelationshipProperties.Count);
                    Assert.IsNotNull(ownerRelProp.ReverseRelationshipProperty);
                    Assert.IsNotNull(ownerRelProp.RelatedPropertyName);
                    Assert.AreEqual(2, fromSolution.Assemblies[0].Classes.Count, "Should have owner and related class for the relationship");

                    Assert.AreEqual(0, ownerToClass.RelationshipsDM.Count);
                    Assert.AreEqual(1, ownerToClass.Properties.Count);
                    Assert.IsNotNull(ownerToClass.Assembly);
                    Assert.AreSame(toSolution, ownerToClass.Solution);
                    Assert.AreEqual(1, toSolution.Assemblies[0].Classes.Count, "Should have owner and related class for the relationship");
                    //---------------Execute Test ----------------------
                    var mergedSolution = new DBMergeBO<DMSolution>().MergeBOFrom(fromSolution, toSolution);
                    DMSolutionPostLoadProcessor processor = new DMSolutionPostLoadProcessor(new AutoResolvingUnityContainer());
                    processor.ProcessSolution(mergedSolution);
                    //---------------Test Result -----------------------
                    Assert.AreSame(mergedSolution, toSolution);
                    Assert.AreSame(mergedSolution, ownerToClass.Solution);
                    Assert.AreEqual(1, mergedSolution.Assemblies.Count);

                    var mergedAssembly = mergedSolution.Assemblies[0];
                    Assert.AreEqual(2, mergedAssembly.Classes.Count, "Created New Related Class");
                    Assert.AreEqual(1, ownerToClass.RelationshipsDM.Count);
                    var toRelationship = ownerToClass.RelationshipsDM[0];
                    Assert.IsNotNull(toRelationship.ReverseRelationship, "The reverse relationship should be fixed in the Post Load Processor");

                    Assert.AreEqual(1, toRelationship.RelationshipProperties.Count);
                    var toFKColumn = toRelationship.RelationshipProperties[0];
                    Assert.AreEqual(ownerRelProp.RelatedPropertyName, toFKColumn.RelatedPropertyName);
                    Assert.IsNotNull(toFKColumn.RelatedProperty, "The reverse  should be fixed in the Post Load Processor");
                    Assert.IsNotNull(toFKColumn.ReverseRelationshipProperty, "The reverse  should be fixed in the Post Load Processor");

                    //Check Reverse Relationship created on RelatedClass
                    var relatedToClass = mergedAssembly.Classes.Find(@class => @class != ownerToClass);
                    Assert.AreEqual(1, relatedToClass.RelationshipsDM.Count);
                    var reverseToRelationship = relatedToClass.RelationshipsDM[0];
                    Assert.AreEqual(ownerToClass.ClassNameBO, reverseToRelationship.RelatedClassName);
                    Assert.IsNotNull(reverseToRelationship.ReverseRelationship, "The reverse relationship should be fixed in the Post Load Processor");
                    Assert.AreSame(toRelationship, reverseToRelationship.ReverseRelationship, "The reverse relationship should be fixed in the Post Load Processor");
                    Assert.AreEqual(1, reverseToRelationship.RelationshipProperties.Count);
                    var reverseToRelProp = reverseToRelationship.RelationshipProperties[0];
                    Assert.IsNotNull(reverseToRelProp.RelatedProperty, "The reverse  should be fixed in the Post Load Processorl");
                    Assert.IsNotNull(reverseToRelProp.ReverseRelationshipProperty, "The reverse relationship should be fixed in the Post Load Processor");
                    Assert.AreEqual(ownerProp.PropertyName, reverseToRelProp.RelatedPropertyName, "The reverse relationship should be fixed in the Post Load Processor");
                }

                */
/*
        private static void SetRelatedClass(DBForeignKey fromRelationship, DMClass relatedFromClass, DBForeignKeyColumn ownerRelProp, DMProperty relatedProp)
        {
            fromRelationship.RelatedClass = relatedFromClass;
            ownerRelProp.RelatedProperty = relatedProp;
            TestUtilsDMRelationship.GetTestFactory().UpdateCompulsoryProperties(fromRelationship.ReverseRelationship);
            fromRelationship.ReverseRelationship.RelationshipName = TestUtilsShared.GetRandomString();
        }

        private static DMAssembly GetValidAssembly(DMSolution solution)
        {
            return TestUtilsDMAssembly.GetTestFactory()
                .WithValue(assembly => assembly.Solution, solution)
                .CreateValidBusinessObject();
        }

        private static void SetRelatedClass(DBForeignKey ownerRelationship, DBForeignKeyColumn ownerRelProp)
        {
            DMProperty relatedProp;
            DMClass relatedFromClass = GetClassWithOneProp(out relatedProp);

            ownerRelationship.RelatedClass = relatedFromClass;
            ownerRelProp.RelatedProperty = relatedProp;
            TestUtilsDMRelationship.GetTestFactory().UpdateCompulsoryProperties(ownerRelationship.ReverseRelationship);
            ownerRelationship.ReverseRelationship.RelationshipName = TestUtilsShared.GetRandomString();
        }*/

    }
}